package packagerars;

import com.enterprisedt.net.ftp.FTPTransferType;
import com.enterprisedt.net.ftp.FileTransferClient;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.swing.JTextArea;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 *
 * @author Ronald
 */
public class Compresor {

    /**
     * logger : Objeto encargado de los log en la aplicacion.
     */
    private  final Log logger = LogFactory.getLog(Compresor.class);
    /**
     * Constante que define el buffer del archivo a comprimir.
     */
    private  final int bufferSize = 4096;
    /**
     * parametros del shell .
     */
    private  Map params = null;
    /**
     * filesZip .
     */
    private  List filesZip = new ArrayList();
    /**
     * filesZip .
     */
    /**
     * swZipGeneral .
     */
    private  boolean swZipGeneral = false;
    /**
     * swArchivosNoAgrupados.
     */
    private  boolean swArchivosNoAgrupados = false;
    /**
     * sufijo .
     */
    private  String sufijo = ";archivo.zip";
    /**
     * formateador de la fecha .
     */
    private SimpleDateFormat formateador =
            new SimpleDateFormat("dd-MM-yyyy-hh-mm");
    /**
     * Fecha de creacion del archivos .
     */
    private String fecha = formateador.format(new Date());
    /**
     * nombreArchivoZipGeneral .
     */
    private  String nombreArchivoZipGeneral =
            "personalizacion" + fecha + ".zip";
    /**
     * PLANTILLA_HTML .
     */
    private static final String PLANTILLA_HTML = "<HTML>"
                    + "<HEAD>"
                    + "    <TITLE>Detalle de Facturas Enviadas</TITLE>"
                    + "   <style type='text/css'>"
                    + "       table,td,th {"
                    + "           border-collapse:collapse;"
                    + "           margin:0;"
                    + "         padding:0;"
                    + "    }"
                    + " table {"
                    + "  border: none;"
                    + " font-family: Garamond, Georgia,"
                    + " 'Times New Roman', Times, serif;"
                    + "}"
                    + "table caption {"
                    + "background-color: transparent;"
                    + "background-image: url(cap_bg.gif);"
                    + "background-repeat: repeat-x;"
                    + "background-position: bottom left;"
                    + "text-align:left;"
                    + "font-size:150%;"
                    + "text-transform:uppercase;"
                    + "line-height: 30px;"
                    + "letter-spacing:0px;"
                    + "}"
                    + "td, th{"
                    + "                vertical-align:top;"
                    + "                font-weight:normal;"
                    + "            }"
                    + "            thead {"
                    + "                border-left:1px solid #2293FF;"
                    + "            }"
                    + "            thead th {"
                    + "                background: #2293FF;"
                    + "                color: #FFFFFF;"
                    + "                font-size: 125%;"
                    + "                border-top:1px solid #2293FF;"
                    + "                border-right:1px solid #2293FF;"
                    + "                padding: 4px 0.4em 4px 0.4em;"
                    + "            }"
                    + "tfoot td, tfoot th {"
                    + "                border-top:1px solid #2293FF;"
                    + "                border-right: none;"
                    + "                font-weight: bolder;"
                    + "                font-size: 110%;"
                    + "                padding: 0.4em 0.5em 0.4em 0.5em;"
                    + "            }"
                    + "            tbody td, tbody th {"
                    + "                background-color: #D9ECFF;"
                    + "                border-right:1px solid #2293FF;"
                    + "                font-size: 110%;"
                    + "                padding: 0.4em 0.5em 0.4em 0.5em;"
                    + "            }"
                    + "            tbody tr.odd th, tbody tr.odd td{"
                    + "                background-color: #BDDFFF;"
                    + "            }"
                    + "            tbody th{"
                    + "                font-weight: bold;"
                    + "                border-left:1px solid #2293FF"
                    + "            }"
                    + "            table a:link, table a:visited,"
                    + " table a:active {"
                    + "                color:#444F66;"
                    + "                background-color: transparent;"
                    + "                text-decoration: underline;"
                    + "            }"
                    + "            table a:hover {"
                    + "                text-decoration:none;"
                    + "                background-color: #1E90FF;"
                    + "                color: #FFFFFF;"
                    + "            }"
                    + "        </style>"
                    + "    </HEAD>"
                    + "    <BODY>"
                    + "        <div align='center'>"
                    + "            <table  >"
                    + "                <tr>"
                    + "                    <td colspan='6' align='center'>"
                    + "                        <b>Detalle de Facturas"
                    + " Enviadas</b>"
                    + "                    </td>"
                    + "                </tr>"
                    + "                <tr>"
                    + "                    <td >"
                    + "                        #"
                    + "                    </td>"
                    + "                    <td >"
                    + "                        Codigo"
                    + "                    </td>"
                    + "                    <td >"
                    + "                        Nombre Cliente"
                    + "                    </td>"
                    + "                    <td >"
                    + "                        fecha"
                    + "                    </td>"
                    + "                    <td >"
                    + "                        Nombre Archivo"
                    + "                    </td>"
                    + "               </tr>";

    /**
     * compresor .
     * @param urlRaiz .
     * @param urlArchivo .
     * @param agrupar .
     * @param userPTF .
     * @param passFTP .
     * @param hostFTP .
     * @param portFTP .
     * @param enviarFTP .
     * @param tAMensaje .
     * @param nombreArchivos .
     */
    public void compresor(final String urlRaiz,
            final String urlArchivo,
            final String agrupar,
            final String userPTF,
            final String passFTP,
            final String hostFTP,
            final String portFTP,
            final boolean enviarFTP,
            final JTextArea tAMensaje,
            final String nombreArchivos) {

        boolean exitoEnvio = false;
        params = new HashMap();
        params.put("urlRaiz", urlRaiz + File.separator);
        params.put("urlAchivo", urlArchivo);
        params.put("agrupar", agrupar);
        params.put("userFTP", userPTF);
        params.put("passFTP", passFTP);
        params.put("hostFTP", hostFTP);
        params.put("portFTP", portFTP);
        logger.info("Inicio compresion.");
        tAMensaje.setText("Inicio compresion...");
        File f = new File(params.get("urlRaiz").toString());
        BufferedReader entrada = null;
        Map mapaCorreo = new HashMap();
        List listaArchivoNoAgrupados = new ArrayList();
        try {
            entrada = new BufferedReader(
                    new FileReader(params.get("urlAchivo").toString()));
            if (f.exists()) {
                int linea = 1;
                while (entrada.ready()) {
                    String texto = entrada.readLine();
                    String[] cadena = texto.split("\\|");
                    if (cadena.length != 9) {
                        logger.info("Problemas con  longitud de la linea:"
                                + linea);
                    }
                    try {
                        Integer.parseInt(cadena[0].substring(0, 2));
                        if (params.get("agrupar").toString().
                                equals("agrupar")) {
                            if (!mapaCorreo.containsKey(cadena[8])) {
                                List listaArchivosAgrupados = new ArrayList();
                                List listaCodigo = new ArrayList();
                                List listaCliente = new ArrayList();
                                List listaFecha = new ArrayList();

                                listaCodigo.add(cadena[0]);
                                listaCliente.add(cadena[1]);
                                listaFecha.add(cadena[5]);
                                listaArchivosAgrupados.add(cadena[7]);
                                Map mapCampos = new HashMap();
                                mapCampos.put("codigos", listaCodigo);
                                mapCampos.put("clientes", listaCliente);
                                mapCampos.put("fechas", listaFecha);
                                mapCampos.put("pdfs", listaArchivosAgrupados);
                                mapaCorreo.put(cadena[8], mapCampos);
                            } else {
                                Map mapTemp = (Map) mapaCorreo.get(cadena[8]);
                                List listaPdfTemp =
                                        (List) mapTemp.get("pdfs");
                                List listaCodigoTemp =
                                        (List) mapTemp.get("codigos");
                                List listaClienteTemp =
                                        (List) mapTemp.get("clientes");
                                List listaFechaTemp =
                                        (List) mapTemp.get("fechas");
                                listaCodigoTemp.add(cadena[0]);
                                listaClienteTemp.add(cadena[1]);
                                listaFechaTemp.add(cadena[5]);
                                listaPdfTemp.add(cadena[7]);
                                mapTemp.put("codigos", listaCodigoTemp);
                                mapTemp.put("clientes", listaClienteTemp);
                                mapTemp.put("fechas", listaFechaTemp);
                                mapTemp.put("pdfs", listaPdfTemp);
                                mapaCorreo.put(cadena[8], mapTemp);
                            }
                        } else {
                            listaArchivoNoAgrupados.add(
                                    cadena[7] + ";" + cadena[8]);
                        }
                    } catch (Exception ex) {
                        logger.info("Problema con la lectura de la linea "
                                + linea);

                    }
                    linea++;
                }
                if (mapaCorreo.size() > 0) {
                    Iterator it = mapaCorreo.entrySet().iterator();
                    while (it.hasNext()) {
                        Map.Entry e = (Map.Entry) it.next();
                        crearIndex((Map) e.getValue(), params.get("urlRaiz").
                                toString() + "index.html");
                        List listaArchivos = new ArrayList();
                        listaArchivos =
                                (List) ((Map) e.getValue()).get("pdfs");
                        listaArchivos.add("index.html");
                        String nomArchivo = e.getKey().toString() + sufijo;
                        comprimir(listaArchivos, params.get("urlRaiz").
                                toString(), nomArchivo);
                        File archivoElminado = new File(params.get("urlRaiz").
                                toString() + "index.html");
                        archivoElminado.delete();
                    }
                } else {
                    if (listaArchivoNoAgrupados.size() > 0) {
                        boolean exitoCompresion = false;
                        if (nombreArchivos == null || nombreArchivos.equals("")
                                || nombreArchivos.equals(" ")) {
                        exitoCompresion = comprimir(listaArchivoNoAgrupados,
                                params.get("urlRaiz").toString(),
                                nombreArchivoZipGeneral);
                        } else {
                            exitoCompresion = comprimir(listaArchivoNoAgrupados,
                                params.get("urlRaiz").toString(),
                                nombreArchivos + ".zip");
                        }
                        if (exitoCompresion) {
                            if (nombreArchivos == null || nombreArchivos.equals("")
                                    || nombreArchivos.equals(" ")) {
                                logger.info("Fin de compresión del archivo. "
                                        + "\nNombre del "
                                        + "archivo:" + nombreArchivoZipGeneral);
                                tAMensaje.setText("Fin de compresión del "
                                        + "archivo. \n Nombre"
                                        + " del archivo: "
                                        + nombreArchivoZipGeneral);

                            } else {
                             logger.info("Fin de compresión del archivo. "
                                        + "\nNombre del "
                                        + "archivo:" + nombreArchivos + ".zip");
                                tAMensaje.setText("Fin de compresión del "
                                        + "archivo. \n Nombre"
                                        + " del archivo: "
                                        + nombreArchivos + ".zip");
                            }
                        } else {
                            tAMensaje.setText("Problemas en el proceso de"
                                    + " compresión,\n"
                                    + "vea el log para mas información  ");
                        }
                        swArchivosNoAgrupados = true;
                        if (enviarFTP && exitoCompresion) {
                            Map param = new HashMap();
                            param.put("host", params.get("hostFTP"));
                            param.put("user", params.get("userFTP"));
                            param.put("pass", params.get("passFTP"));
                            param.put("port", params.get("portFTP"));
                            if (nombreArchivos == null || nombreArchivos.equals("")
                                    || nombreArchivos.equals(" ")) {
                                param.put("urlArchivo", params.get("urlRaiz").
                                        toString() + nombreArchivoZipGeneral);
                                param.put("nomArchivo", nombreArchivoZipGeneral);

                            } else {
                                param.put("urlArchivo", params.get("urlRaiz").
                                        toString() + nombreArchivos + ".zip");
                                param.put("nomArchivo", nombreArchivos + ".zip");
                            }


                            exitoEnvio = enviarArchivo(param, tAMensaje);
                            if (exitoEnvio) {
                                if (nombreArchivos == null || nombreArchivos.equals("")
                                        || nombreArchivos.equals(" ")) {
                                    logger.info("Fin de envio via FTP. \n"
                                            + "Nombre del "
                                            + "archivo:" + nombreArchivoZipGeneral);
                                    tAMensaje.setText("Fin de envio via FTP"
                                            + " \n Nombre"
                                            + " del archivo: "
                                            + nombreArchivoZipGeneral);
                                } else {
                                    logger.info("Fin de envio via FTP. \n"
                                            + "Nombre del "
                                            + "archivo:" + nombreArchivos + ".zip");
                                    tAMensaje.setText("Fin de envio via FTP"
                                            + " \n Nombre"
                                            + " del archivo: "
                                            + nombreArchivos + ".zip");
                                }

                            } else {
                                tAMensaje.setText("Problemas en el envio "
                                        + "via FTP,\n"
                                        + "vea el log para mas información ");
                            }
                        }
                    }
                }
            }
        } catch (IOException ex) {
            logger.error("Problemas con la lectura del archivo: " + ex);
        }
        if (!swArchivosNoAgrupados) {
            swZipGeneral = true;
            logger.info("Inicio de compresión del archivo.");
            tAMensaje.setText("Inicio de compresión del archivo...");
            boolean exitoCompresion = false;
            if (nombreArchivos == null || nombreArchivos.equals("")
                                        || nombreArchivos.equals(" ")) {
                exitoCompresion = comprimir(filesZip,
                    params.get("urlRaiz").toString(),
                    nombreArchivoZipGeneral);
            } else {
                exitoCompresion = comprimir(filesZip,
                    params.get("urlRaiz").toString(),
                    nombreArchivos + ".zip");
            }

            if (exitoCompresion) {
                if (nombreArchivos == null || nombreArchivos.equals("")
                        || nombreArchivos.equals(" ")) {
                    logger.info("Fin de compresión del archivo. \n Nombre del "
                            + "archivo:" + nombreArchivoZipGeneral);
                    tAMensaje.setText("Fin de compresión del archivo. \nNombre"
                            + " del archivo: " + nombreArchivoZipGeneral);
                } else {
                    logger.info("Fin de compresión del archivo. \n Nombre del "
                            + "archivo:" + nombreArchivos + ".zip");
                    tAMensaje.setText("Fin de compresión del archivo. \nNombre"
                            + " del archivo: " + nombreArchivos + ".zip");
                }

            } else {
                tAMensaje.setText("Problemas en el proceso de compresión,\n"
                        + "vea el log para mas información  ");
            }
            if (enviarFTP && exitoCompresion) {
                Map param = new HashMap();
                param.put("host", params.get("hostFTP"));
                param.put("user", params.get("userFTP"));
                param.put("pass", params.get("passFTP"));
                param.put("port", params.get("portFTP"));
                if (nombreArchivos == null || nombreArchivos.equals("")
                        || nombreArchivos.equals(" ")) {
                    param.put("urlArchivo", params.get("urlRaiz").toString()
                            + nombreArchivoZipGeneral);
                    param.put("nomArchivo", nombreArchivoZipGeneral);
                } else {
                    param.put("urlArchivo", params.get("urlRaiz").toString()
                            + nombreArchivos + ".zip");
                    param.put("nomArchivo", nombreArchivos + ".zip");
                }
                exitoEnvio = enviarArchivo(param, tAMensaje);
                if (exitoEnvio) {
                    if (nombreArchivos == null || nombreArchivos.equals("")
                            || nombreArchivos.equals(" ")) {
                        logger.info("Fin de envio via FTP. \n Nombre del "
                                + "archivo:" + nombreArchivoZipGeneral);
                        tAMensaje.setText("Fin de envio via FTP"
                                + " \nNombre"
                                + " del archivo: " + nombreArchivoZipGeneral);
                    } else {
                        logger.info("Fin de envio via FTP. \n Nombre del "
                                + "archivo:" + nombreArchivos + ".zip");
                        tAMensaje.setText("Fin de envio via FTP"
                                + " \nNombre"
                                + " del archivo: " + nombreArchivos + ".zip");
                    }
                } else {
                    tAMensaje.setText("Problemas en el envio via FTP,\n"
                            + "vea el log para mas información  ");
                }
            }
        }

    }

    /**
     * Metodo que comprime los archivos .
     * @param files .
     * @param urlRaz .
     * @param nombreArchivoSalida .
     * @return boolean .
     */
    public  boolean  comprimir(final List files, final String urlRaz,
            final String nombreArchivoSalida) {
        boolean exitoComprimir =  true;
        if (!swZipGeneral) {
            filesZip.add(nombreArchivoSalida);
        }
        try {
            BufferedInputStream origin = null;

            FileOutputStream dest = new FileOutputStream(
                    new File(urlRaz + nombreArchivoSalida));

            ZipOutputStream out = new ZipOutputStream(
                    new BufferedOutputStream(dest));
            byte[] data = new byte[bufferSize];
            for (Iterator i = files.iterator(); i.hasNext();) {
                String[] arrayNombre = ((String) i.next()).split(";");
                String nombreArchivoEntrada = "";
                if (!swZipGeneral) {
                    if (!params.get("agrupar").toString().equals("agrupar")) {
                        nombreArchivoEntrada = arrayNombre[0];
                    } else {
                        nombreArchivoEntrada = arrayNombre[0];
                    }
                } else {
                    nombreArchivoEntrada = arrayNombre[0] + sufijo;
                }
                String filename = urlRaz + nombreArchivoEntrada;
                File file = new File(filename);
                FileInputStream fi = new FileInputStream(file);
                origin = new BufferedInputStream(fi, bufferSize);
                String nombreArchivoComprimido = "";
                if (swArchivosNoAgrupados) {
                    nombreArchivoComprimido = arrayNombre[0];
                } else {
                    if (arrayNombre.length > 1) {
                        if (params.get("agrupar").toString().
                                equals("agrupar")) {
                            nombreArchivoComprimido = arrayNombre[0] + ";"
                                    + arrayNombre[1];
                        } else {
                            nombreArchivoComprimido = arrayNombre[1]
                                    + ";" + arrayNombre[0];
                        }

                    } else {
                        nombreArchivoComprimido = file.getName();
                    }
                }
                ZipEntry entry = new ZipEntry(nombreArchivoComprimido);
                out.putNextEntry(entry);
                int count;
                while ((count = origin.read(data, 0, bufferSize)) != -1) {
                    out.write(data, 0, count);
                }
                origin.close();
                if (swZipGeneral) {
                    if (!file.delete()) {
                        logger.info("Problemas para elminar el archivo"
                                + file.getName());
                    }
                }
            }
            out.close();
        } catch (Exception ex) {
            logger.error("Problemas para comprimir el archivo " + ex);
            exitoComprimir = false;
        }
        return exitoComprimir;
    }

    /**
     * Metodo que crea el arhivo index.html .
     * @param mapCampos .
     * @param urlArchivo .
     */
    public  void crearIndex(final Map mapCampos, final String urlArchivo) {
        FileWriter fichero = null;
        PrintWriter pw = null;
        try {
            File archivo = new File(urlArchivo);
            fichero = new FileWriter(archivo, true);
            pw = new PrintWriter(fichero);
            pw.write(PLANTILLA_HTML);
            Iterator it = mapCampos.entrySet().iterator();
            List listaPdf = new ArrayList();
            List listaCodigo = new ArrayList();
            List listaCliente = new ArrayList();
            List listaFecha = new ArrayList();
            while (it.hasNext()) {
                Map.Entry e = (Map.Entry) it.next();
                if (e.getKey().equals("codigos")) {
                    listaCodigo = (List) e.getValue();
                }
                if (e.getKey().equals("pdfs")) {
                    listaPdf = (List) e.getValue();
                }
                if (e.getKey().equals("clientes")) {
                    listaCliente = (List) e.getValue();
                }
                if (e.getKey().equals("fechas")) {
                    listaFecha = (List) e.getValue();
                }
            }
            for (int i = 0; i < listaCliente.size(); i++) {
                String cliente = (String) listaCliente.get(i);
                String pdf = (String) listaPdf.get(i);
                String codigo = (String) listaCodigo.get(i);
                String fechaIndex = (String) listaFecha.get(i);
                pw.write("        <tr>"
                        + "            <td >"
                        + new Integer(i + 1)
                        + "            </td>"
                        + "            <td >"
                        + "                <a href='" + pdf + "'>"
                        + codigo
                        + "                 </a>"
                        + "            </td>"
                        + "            <td >"
                        + "                <a href='" + pdf + "'>"
                        + cliente
                        + "                </a>"
                        + "            </td>"
                        + "            <td >"
                        + "                <a href='" + pdf + "'>"
                        + fechaIndex
                        + "                </a>"
                        + "            </td>"
                        + "            <td >"
                        + "                <a href='" + pdf + "'>"
                        + pdf
                        + "                    </a>"
                        + "            </td>"
                        + "         </tr>");
            }

            pw.write("</table> "
                    + " </div> "
                    + "</BODY> "
                    + "</HTML> ");
            fichero.close();
        } catch (Exception e) {
            logger.error("Problemar creando el archivo index.html:" + e);
        }
    }

    /**
     *
     *Metodo encargado de enviar archivo via ftp.
     * @param newParams .
     * @param tAMensaje .
     * @return  boolean .
     */
    public  boolean enviarArchivo(final Map newParams,
            final JTextArea tAMensaje) {
        boolean exitoEnvio = true;
        FileTransferClient ftpTransferClient = new FileTransferClient();
        try {
            ftpTransferClient.setRemoteHost((String) newParams.get("host"));
            ftpTransferClient.setUserName((String) newParams.get("user"));
            ftpTransferClient.setPassword((String) newParams.get("pass"));
            ftpTransferClient.setRemotePort((
                    new Integer((String) newParams.get("port"))));
            ftpTransferClient.connect();
            ftpTransferClient.setContentType(FTPTransferType.BINARY);
            ftpTransferClient.changeDirectory("/");
            ftpTransferClient.setDetectContentType(true);
            File source = new File((String) newParams.get("urlArchivo"));
            OutputStream os = ftpTransferClient.uploadStream(
                    (String) newParams.get("nomArchivo"));
            FileInputStream fis = new FileInputStream(source);
            long fin = source.length();
            long ini = 0;
            int x = 0;
            byte[] b = new byte[2048];
            while ((x = fis.read(b)) > 0) {
                ini += x;
                os.write(b, 0, x);
            }
            os.close();
            fis.close();
        } catch (Exception ex) {
            exitoEnvio = false;
        }
        return exitoEnvio;
    }

}
